from itertools import groupby

from django_filters.rest_framework import DjangoFilterBackend
from rest_framework.filters import OrderingFilter
from rest_framework import mixins, viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import action
from rest_framework.views import APIView, Response, status
from django.db.models import Prefetch, Max

from utils.common import Pagination
from apps.common.account.models import Account
from .models import Faculty, Zzbmb, Major, Classes, Zyb, Bjb
from .serializers import FacultySerializer, ClassListSerializer, MajorListSerializer
from .utils import get_second_faculty_by_perms


class ClassesViewSet(mixins.ListModelMixin,
                     viewsets.GenericViewSet):
    queryset = Classes.objects.all()
    serializer_class = ClassListSerializer
    # permission_classes = [IsAuthenticated]
    filter_backends = (DjangoFilterBackend,)

    @action(methods=['post'], detail=False, url_path='update_classes')
    def update_classes_from_bjb(self, request, pk=None):
        """ 从学校班级表同步班级数据 """
        classes_qs = Bjb.objects.all().values()
        data_dict = {i['class_code']: i for i in classes_qs}
        for code, class_data in data_dict.items():
                obj, created = Classes.objects.update_or_create(class_code=code,
                                                                defaults={
                                                                    'class_name': class_data['class_name'],
                                                                    'faculty_code': class_data['faculty_code'],
                                                                    'major_code': class_data['major_code'],
                                                                    'grade_name': class_data['grade_name'],
                                                                    'campus': class_data['campus'],
                                                                    'class_type': class_data['class_type'],
                                                                })
        Classes.objects.exclude(class_code__in=data_dict.keys()).delete()
        return Response({'message': '同步完成！'})

    @action(methods=['get'], detail=False, url_path='class_cascader')
    def get_class_cascader(self, request, pk=None):
        """
           获取班级的级联选择器数据
           data的格式如下：
           data = [
                    {
                       'name':'2018级',
                       'children': [
                                      {
                                         'name': '计算机科学与技术学院',
                                          'children': [
                                                         {
                                                             'name': '物联网1班',
                                                              'class_code': '2002'
                                                         }
                                          ]
                                      }
                       ]
                    }
           ]
        """
        max_grade_name = Account.objects.filter(type="本科生", status="在读").aggregate(Max('grade_name'))
        grade_name_ls = [int(max_grade_name['grade_name__max']) - i for i in range(4)]
        class_qs = Classes.objects.filter(grade_name__in=grade_name_ls, class_type="本科生")\
            .values()
        for i in class_qs:
            i['name'] = i['class_name']
            i['value'] = f"class_{i['class_code']}"
        faculty_qs = Faculty.objects.all().values('faculty_code', 'faculty_title')
        faculty_dict = {i['faculty_code']: i['faculty_title'] for i in faculty_qs}
        groupby_grade_list = [{'name': f"{k}级", 'value': f"grade_{k}", 'children': list(g)}
                              for k, g in groupby(sorted(list(class_qs), key=lambda s: s['grade_name']),
                                                  lambda x: x['grade_name'])]

        for grade in groupby_grade_list:
            grade['children'] = [{'value': f"faculty_{k}", 'children': list(g), 'name': faculty_dict.get(k, None)}
                                 for k, g in groupby(sorted(grade['children'], key=lambda s: s['faculty_code']),
                                                     lambda x: x['faculty_code'])]
        data = groupby_grade_list
        return Response(data)


class MajorViewSet(mixins.ListModelMixin,
                   viewsets.GenericViewSet):
    queryset = Major.objects.all()
    serializer_class = MajorListSerializer
    # permission_classes = [IsAuthenticated]
    filter_backends = (DjangoFilterBackend,)

    @action(methods=['post'], detail=False, url_path='update_major')
    def update_major_from_zyb(self, request, pk=None):
        """ 从学校专业表同步专业数据 """
        major_qs = Zyb.objects.all().values()
        data_dict = {i['major_code']: i for i in major_qs}
        for code, major_data in data_dict.items():
            obj, created = Major.objects.update_or_create(major_code=code,
                                                          defaults={
                                                              'major_title': major_data['major_title'],
                                                              'faculty_code': major_data['faculty_code']
                                                          })
        Major.objects.exclude(major_code__in=data_dict.keys()).delete()
        return Response({'message': '同步完成！'})


class FacultyViewSet(mixins.ListModelMixin,
                     viewsets.GenericViewSet):
    queryset = Faculty.objects.all()
    filter_backends = (DjangoFilterBackend, OrderingFilter)
    # permission_classes = [IsAuthenticated]
    serializer_class = FacultySerializer
    pagination_class = Pagination
    ordering_fields = ('id', )

    @action(methods=['post'], detail=False, url_path='update_faculty')
    def update_faculty_from_zzbmb(self, request, pk=None):
        """ 从学校组织部门表同步部门数据 """
        faculty_qs = Zzbmb.objects.all().values()
        data_dict = {i['faculty_code']: i for i in faculty_qs}
        for code, faculty_data in data_dict.items():
            obj, created = Faculty.objects.update_or_create(faculty_code=code,
                                                            defaults={
                                                                'faculty_title': faculty_data['faculty_title'],
                                                                'parent_code': faculty_data['parent_code']
                                                            })
        Faculty.objects.exclude(faculty_code__in=data_dict.keys()).delete()
        return Response({'message': '同步完成！'})

    @action(methods=['get'], detail=False, url_path='second_faculty')
    def get_second_faculty(self, request, pk=None):
        """ 获取用户有权限查看的二级单位 """

        # 获取所有二级单位
        # first_faculty_codes = Faculty.objects.filter(parent_code__isnull=True)\
        #     .values_list('faculty_code', flat=True)
        # second_faculty_data = Faculty.objects\
        #     .filter(parent_code__in=first_faculty_codes)\
        #     .values('id', 'faculty_code', 'faculty_title')
        #
        second_faculty_data = Faculty.objects.all()\
            .values('id', 'faculty_code', 'faculty_title')

        res_data = second_faculty_data
        return Response({'data': res_data})
